﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace GMap.NET.WindowsForms
{
   /// <summary>
   /// 包络线
   /// </summary>
   public class GMapEnvelope
   {
      public GMapEnvelope(params GMapCircle[] circles)
      {
         Circles = new List<GMapCircle>();
         Circles.AddRange(circles);
      }

      public List<GMapCircle> Circles
      {
         get;
         set;
      }

      GMapOverlay overlay;
      public GMapOverlay Overlay
      {
         get
         {
            return overlay;
         }
         internal set
         {
            overlay = value;
         }
      }

      private bool visible = true;

      /// <summary>
      /// is polygon visible
      /// </summary>
      public bool IsVisible
      {
         get
         {
            return visible;
         }
         set
         {
            if (value != visible)
            {
               visible = value;

               if (Overlay != null && Overlay.Control != null)
               {
                  if (visible)
                  {
                     Overlay.Control.UpdateEnvelopeLocalPosition(this);
                  }
                  else
                  {
                     if (Overlay.Control.IsMouseOverPolygon)
                     {
                        Overlay.Control.IsMouseOverPolygon = false;
#if !PocketPC
                        Overlay.Control.RestoreCursorOnLeave();
#endif
                     }
                  }

                  {
                     if (!Overlay.Control.HoldInvalidation)
                     {
                        Overlay.Control.Invalidate();
                     }
                  }
               }
            }
         }
      }

      /// <summary>
      /// can receive input
      /// </summary>
      public bool IsHitTestVisible = false;

      private bool isMouseOver = false;

      /// <summary>
      /// is mouse over
      /// </summary>
      public bool IsMouseOver
      {
         get
         {
            return isMouseOver;
         }
         internal set
         {
            isMouseOver = value;
         }
      }

      Region region;

      internal void UpdateRegion()
      {
         var path = new GraphicsPath();
         for (int i = 0; i < this.Circles.Count; i++)
         {

            var scale = Math.Pow(2, (18 - Overlay.Control.Zoom)) * 0.5971642833709717;
            var radius = this.Circles[i].Radius / scale;

            RectangleF rect = new RectangleF(this.Circles[i].LocalCenter.X - (float)radius, this.Circles[i].LocalCenter.Y - (float)radius, 2 * (float)radius, 2 * (float)radius);

            if (i == 0)
            {
               path.AddEllipse(rect);
               region = new Region(path);
            }
            else
            {
               var otherpath = new GraphicsPath();
               otherpath.AddEllipse(rect);
               region.Union(otherpath);
            }
         }
      }

      /// <summary>
      /// Indicates whether the specified point is contained within this System.Drawing.Drawing2D.GraphicsPath
      /// </summary>
      /// <param name="x"></param>
      /// <param name="y"></param>
      /// <returns></returns>
      internal bool IsInsideLocal(int x, int y)
      {
         if (region != null)
         {
            return region.IsVisible(x, y);
         }
         return false;
      }


      /// <summary>
      /// 绘制
      /// </summary>
      /// <param name="g"></param>
      public virtual void OnRender(Graphics g)
      {
         if (IsVisible)
         {
            IntPtr hBrush = CreateSolidBrush(ColorTranslator.ToWin32(this.Stroke.Color));
            IntPtr hRgn = region.GetHrgn(g);
            IntPtr hdc = g.GetHdc();
            FrameRgn(hdc, hRgn, hBrush, 1, 1);
            g.ReleaseHdc();
            //g.DrawPath(envelop.Stroke, path);
            g.FillRegion(this.Fill, region);
         }
      }


      public static readonly Pen DefaultStroke = new Pen(Color.FromArgb(155, Color.MidnightBlue));
      //边线
      public Pen Stroke = DefaultStroke;

      public static readonly Brush DefaultFill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue));
      //填充
      public Brush Fill = DefaultFill;

      [DllImport("gdi32.dll", EntryPoint = "FrameRgn")]
      public static extern int FrameRgn(
         IntPtr hdc, // handle to device context
         IntPtr hrgn, // handle to region to be framed
         IntPtr hbr, // handle to brush used to draw border
         int nWidth, // width of region frame
         int nHeight);

      [DllImport("gdi32.dll")]
      public static extern IntPtr CreateSolidBrush(int crColor);

   }

   public delegate void EnvelopeClick(GMapEnvelope item, MouseEventArgs e);
   public delegate void EnvelopeEnter(GMapEnvelope item);
   public delegate void EnvelopeLeave(GMapEnvelope item);
   public delegate void EnvelopeDoubleClick(GMapEnvelope item, MouseEventArgs e);
}
